#include <iostream>
#include <string>
#include <memory>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include <unistd.h>
#include <pthread.h>

#include <cstring>
#include <cstdlib>
#include <ctime>

#include "Protocol.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"

void Usage(std::string proc)
{
    std::cout << "Usage:\n\t" << proc << " serverip serverport\n"<< std::endl;
}

//构建请求
class ReqFactory
{
public:
    ReqFactory()
    {
        srand(time(nullptr)^pthread_self());
        _operset="+-*/%^&|";
    }

    std::shared_ptr<Request> BuildRequest()
    {
        int x=rand()%10+1;
        usleep(x*10);
        int y=rand()%5;//取值范围[0,1,2,3,4]
        usleep(y*5);
        char oper=_operset[rand() % _operset.size()];//下标范围:[0,size-1]]

        std::shared_ptr<Request> req(new Request(x,y,oper));
        return req;
    }

    std::shared_ptr<Response> BuildResponse()
    {
        std::shared_ptr<Response> resp(new Response());
        return resp;
    }
    ~ReqFactory()
    {}
private:
    std::string _operset;
};



//./cal_client serverip serverport
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    std::string serverip=argv[1];
    uint16_t serverport=std::stoi(argv[2]);

    std::unique_ptr<Socket> tcl(new TcpSocket());

    ReqFactory factory;
    //创建套接字&&绑定&&发送连接请求
    InetAddr serveraddr(serverip,serverport);
    bool res=tcl->BuildClientSocket(serveraddr);
    std::string inbuffer;
    while(res)
    {
        sleep(1);
        //1.构建Request请求
        std::shared_ptr<Request> req=factory.BuildRequest();

        //2.对Requset请求进行序列化
        std::string message;
        req->Serialize(&message);
        //2.1 查看序列化之后的结果
        std::cout<<"客户端序列化:\n"<<message<<std::endl;

        //3.添加协议报头 string Encode(const string& json_str)
        string send_str=Encode(message);
         std::cout<<"客户端添加报头:\n"<<send_str<<std::endl;

        //4."len"\r\n"{json_str}"\r\n" 发送请求
        int n=tcl->Send(send_str);
        if(n<0)
        {
            std::cout<<"send error"<<std::endl;
            break;
        }


        //5.接收服务端处理结果Response
        tcl->Recv(&inbuffer);

        //6.检测Resonse序列化字符串是否为完整的响应 string Decode(string& message)
        string package=Decode(inbuffer);
        if(package.empty())
        {
            continue;
        }
        //7.对获取到的完整的响应做反序列化处理
       std::shared_ptr<Response> resp=factory.BuildResponse();
       resp->Deserialize(package);

        //8.显示结果
        std::cout<<resp->_result<<"["<<resp->_code<<"]"<<std::endl;
    }
    return 0;
}